﻿using System.Diagnostics.Contracts;

namespace Guia.Core
{
    using System;

    /// <summary>
    /// This class can be used to run actions whith a defined timeout.
    /// </summary>
    public class Clock
    {
        /// <summary>
        /// Runs a specific action. After the defined timeout is reached, the processing is aborted and the timeoutAction will be performed.
        /// </summary>
        /// <param name="action">
        /// The action to run.
        /// </param>
        /// <param name="timeoutAction">
        /// The timeout action. Will be run if a timeout is reached
        /// </param>
        /// <param name="timeout">
        /// The timeout time in milliseconds.
        /// </param>
        /// <exception cref="ArgumentNullException" />
        /// /// <exception cref="ArgumentException" />
        public static void Run(Action action, Action timeoutAction, int timeout)
        {
            Contract.Requires<ArgumentNullException>(action != null);
            Contract.Requires<ArgumentNullException>(timeoutAction != null);
            Contract.Requires<ArgumentException>(timeout > 0);
            IAsyncResult result = action.BeginInvoke(null, null);
            if (result.AsyncWaitHandle.WaitOne(timeout))
            {
                action.EndInvoke(result);
            }
            else
            {
                timeoutAction.Invoke();
            }
        }
    }
}
